;;;; zathura-tools.lisp

(in-package #:zathura)

(defun zathura:processes ()
  (loop for line in (uiop:run-program '("qdbus" "org.pwmt.zathura.*") :output :lines)
        for hyphen-pos = (position #\- line)
        collect (parse-integer line :start (1+ hyphen-pos))))

(defun zathura-dbus (pid message &rest args)
  (values (uiop:run-program `("qdbus"
                              ,(format nil "org.pwmt.zathura.PID-~D" pid)
                              "/org/pwmt/zathura"
                              ,(format nil "org.pwmt.zathura.~A" message)
                              ,@(mapcar #'write-to-string args))
                            :output '(:string :stripped t))))

(defun zathura:filename (pid)
  (check-type pid (integer 0 *))
  (zathura-dbus pid "filename"))

(defun zathura:page (pid)
  (check-type pid (integer 0 *))
  (1+ (parse-integer (zathura-dbus pid "pagenumber"))))

(defun (setf zathura:page) (page pid)
  (check-type pid (integer 0 *))
  (check-type page (or null (integer 0 *)))
  (when (string= (zathura-dbus pid "GotoPage" (1- page)) "false")
    (error "Failed to set page in Zathura"))
  page)

(defun zathura:zathura (file &key page)
  (uiop:launch-program `("zathura" ,@(and page (list (format nil "--page=~D" page))) ,(namestring file))))

(defun zathura:zopen (pathname &key page reuse)
  "Open given pathname in zathura and return PID.  The PAGE argument is as in ZATHURA:ZATHURA.  If REUSE is true, try to find an existing window with the file and raise it."
  (check-type page (or null (integer 0 *))) 
  (let* ((filename (uiop:unix-namestring (truename pathname)))
         (pid (and reuse (find filename (zathura:processes) :key #'zathura:filename :test #'string=))))
    (if pid
        (progn
          (when page
            (setf (zathura:page pid) page))
          (xwin:raise (xwin:by-pid pid))
          pid)
        (uiop:process-info-pid (zathura:zathura filename :page page))))) 
